﻿local tonumber = tonumber;
local floor = floor;
local ceil = ceil;
local max = max;
local log = log;
local tinsert = tinsert;
local select = select;
local format = format;
local CreateFrame = CreateFrame;
local GetArenaCurrency = GetArenaCurrency;
local GetArenaTeam = GetArenaTeam;
local GetNumArenaTeamMembers = GetNumArenaTeamMembers;
local GetArenaTeamRosterInfo = GetArenaTeamRosterInfo;

local maxPoint, maxRating, PVPFrameArenaRating = 0, 0;
local tAP = CreateFrame("Frame");
tAP.teamSize = {[2] = 0.76, [3] = 0.88, [5] = 1,};
tAP.teamPoint = {[2] = 261, [3] = 303, [5] = 344};
tAP.cale = {}

tAP.name = "tdArenaPoints"
InterfaceOptions_AddCategory(tAP);

local locale = GetLocale()
local L = locale == "zhCN" and {
	pointcale = "点数计算器",
	ratingcale = "等级计算器",
	timecale = "时间计算器",
	choosecale = "选择计算器",
	level = "等级:",
	size = "规模",
	point = "点数",
	no = "|cff555555不可行|r",
	itemprice = "物品价格:",
	nowpoint = "现有点数:",
	needpoint = "需要点数:",
	week0 = "第#周",
	week = "|cffff00ff第%d周|r",
	week2 = "%d 周",
	vlevel = "平均等级:",
	tooltip = "点击打开点数计算器。",
	prating = "个人等级",
	time = "时间",
} or locale == "zhTW" and {
	pointcale = "點數計算器",
	ratingcale = "等級計算器",
	timecale = "時間計算器",
	choosecale = "選擇計算器",
	level = "等級:",
	size = "規模",
	point = "點數",
	no = "|cff555555不可行|r",
	itemprice = "物品價格:",
	nowpoint = "現有點數:",
	needpoint = "需要點數:",
	week0 = "第#周",
	week = "|cffff00ff第%d周|r",
	week2 = "%d 周",
	vlevel = "平均等級:",
	tooltip = "點擊打開點數計算器。",
	prating = "個人等級",
	time = "時間", 
} or {
	pointcale = "Points calculator",
	ratingcale = "Rating calculator",
	timecale = "Time calculator",
	choosecale = "chooses the calculator",
	level = "Rating: ",
	size = "Size",
	point = "Points",
	no = "|cff555555No|r",
	itemprice = "Item price: ",
	nowpoint = "Existing points: ",
	needpoint = "Needs the points: ",
	week0 = "#",
	week = "|cffff00ffWeek: %d|r",
	week2 = "%d Week",
	vlevel = "Average Rating: ",
	tooltip = "The click turns on the points calculator.",
	prating = "Player Rating:",
	time = "Time", 
}

function tAP:CheckNum(value)
	return value <= 0 and 1 or value;
end

function tAP:RatingToPoint(rating, size)
	if not (size and self.teamSize[size]) then
		return 0;
	else
		rating = tonumber(rating) or 0;
		local points;
		if rating <= 1500 then
			points = 0.22 * rating + 14;
		else
			points =  1511.26 / ( 1 + 1639.28 * 2.71828 ^(-0.00412*rating) );
		end
		return floor(points * self.teamSize[size]);
	end
end

function tAP:PointToRating(point, size)
	if not (size and self.teamSize[size]) then
		return 0;
	else
		point = tonumber(point) or 0;
		if point > self.teamPoint[size] then
			return ceil(log( self:CheckNum((1511.26 * self.teamSize[size] / point - 1) / 1639.28) ) / -0.00412);
		else
			return ceil(max((point/self.teamSize[size] - 14) / 0.22, 0));
		end
	end
end

do
	local font, size, outline = GameFontHighlightSmall:GetFont();
	local function CreateLabel(parent, text, fontheight, point, rpoint, x, y)
		if parent and text then
			local label = parent:CreateFontString(nil, "OVERLAY");
			label:SetJustifyH("LEFT");
			label:SetFont(font, fontheight, outline)
			label:SetHeight(fontheight);
			label:SetText(text);
			label:SetPoint(point, parent, rpoint, x, y);
			return label;
		end
	end
	
	local function CreatePanel(text)
		local frame = CreateFrame("Frame", nil, tAP);
		frame:SetBackdrop{
			edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
			edgeSize = 16, tileSize = 16, tile = true, 
			insets = {left = 5, right = 5, top = 5, bottom = 5}
		}
		frame:SetBackdropBorderColor(0.4, 0.4, 0.4);
		frame:SetBackdropColor(0.15, 0.15, 0.15, 0.5);
		frame:SetPoint("TOPLEFT", 10, -30)
		frame:SetPoint("BOTTOMRIGHT", -10, 10)
		frame:Hide()
		
		frame.id = #(tAP.cale) + 1
		tinsert(tAP.cale, frame)
		
		CreateLabel(frame, text, 18, "BOTTOMLEFT", "TOPLEFT", 5, -2);
		return frame
	end
	
	local function CreateEditBox(parent, text, func, showfunc)
		local frame = CreateFrame("EditBox", nil, parent);
		frame:SetAutoFocus(nil);
		frame:SetWidth(170);
		frame:SetHeight(23);
		frame:SetBackdrop{
			bgFile = "Interface/ChatFrame/ChatFrameBackground",
			edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
			edgeSize = 14, tileSize = 20, tile = true, 
			insets = {left = 2, right = 2, top = 2, bottom = 2}
		}
		frame:SetBackdropColor(0, 0, 0, 0.4);
		frame:SetBackdropBorderColor(0.4, 0.4, 0.4);
		frame:SetTextInsets(8, 8, 0, 0);
		frame:SetFontObject("ChatFontNormal");
		frame:SetNumeric(true);
	
		frame:SetScript("OnTextChanged", func)
		frame:SetScript("OnShow", showfunc);
		frame:SetScript("OnEscapePressed", function(self) self:ClearFocus(); end)
		frame:SetScript("OnEnterPressed", function(self) self:ClearFocus(); end)
		frame:SetScript("OnEditFocusGained", function(self) self.focus = true end)
		frame:SetScript("OnEditFocusLost", function(self) self.focus = nil end)
		
		function frame:IsFocus()
			return self.focus
		end
		
		CreateLabel(frame, text, 14, "RIGHT", "LEFT", -30, 0);
		return frame
	end
	
	local cales = {L.pointcale, L.ratingcale, L.timecale};
	local dropdown = CreateFrame("Frame", "tdArenaPointsCaleDropdown", tAP, "UIDropDownMenuTemplate");
	UIDropDownMenu_SetWidth(dropdown, 152);
	UIDropDownMenu_Initialize(dropdown, function()
		local info = {owner = dropdown, notCheckable = 1, func = function(self)
			for i, v in ipairs(tAP.cale) do
				v:Hide()
			end
			tAP.cale[self.value]:Show();
		end,};
		for i, v in ipairs(cales) do
			info.value = i
			info.text = v
			UIDropDownMenu_AddButton(info, 1)
		end
	end, "MENU");
	dropdown:Hide();
	local button = CreateFrame("Button", nil, tAP, "UIPanelButtonTemplate");
	button.dropdown = dropdown
	button:SetWidth(120); button:SetHeight(22);
	button:SetPoint("TOPRIGHT", -10, -10)
	button:SetScript("OnClick", function(self) ToggleDropDownMenu(1, nil, self.dropdown, self, 0, 0) end)
	button:SetText(L.choosecale)
	
	local frame, editbox, label
	frame = CreatePanel(cales[1]);
	
	editbox = CreateEditBox(frame, L.level, function(self)
		local value = self:GetNumber();
		local parent = self:GetParent();
		parent.p2:SetText(tAP:RatingToPoint(value, 2))
		parent.p3:SetText(tAP:RatingToPoint(value, 3))
		parent.p5:SetText(tAP:RatingToPoint(value, 5))
	end)
	editbox:SetPoint("TOP", 30, -30)
	
	CreateLabel(frame, L.size, 18, "TOPLEFT", "TOPLEFT", 30,-80)
	CreateLabel(frame, "2v2", 36, "TOPLEFT", "TOPLEFT", 30,-130)
	CreateLabel(frame, "3v3", 36, "TOPLEFT", "TOPLEFT", 30,-230)
	CreateLabel(frame, "5v5", 36, "TOPLEFT", "TOPLEFT", 30,-330)
	
	CreateLabel(frame, L.point, 18, "TOPRIGHT", "TOPRIGHT", -30,-80)
	frame.p2 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-130)
	frame.p3 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-230)
	frame.p5 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-330)
	frame:Show();
	
	frame = CreatePanel(cales[2]);
	function frame:GetValues()
		return self.itemprice:GetNumber(), self.nowpoint:GetNumber(), self.needpoint:GetNumber()
	end
	function frame:Update(needpoint)
		needpoint = needpoint or select(3, self:GetValues())
		for i = 1, 12 do
			for _, j in ipairs({2, 3, 5}) do
				value = tAP:PointToRating(needpoint/i, j)
				self["r"..i..j]:SetText(value <= 0 and L.no or value)
			end
		end
	end
	
	editbox = CreateEditBox(frame, L.itemprice, function(self)
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if itemprice - nowpoint ~= needpoint then
			parent.needpoint:SetText(itemprice - nowpoint);
			parent:Update(itemprice - nowpoint)
		end
	end);
	editbox:SetPoint("TOP", 30, -5);
	frame.itemprice = editbox
	
	editbox = CreateEditBox(frame, L.nowpoint, function(self)
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if itemprice - nowpoint ~= needpoint then
			parent.needpoint:SetText(itemprice - nowpoint);
			parent:Update(itemprice - nowpoint);
		end
	end, function(self)
		self:SetText(tonumber(GetArenaCurrency()) or 0);
	end)
	editbox:SetPoint("TOP", 30, -25);
	frame.nowpoint = editbox
	
	editbox = CreateEditBox(frame, L.needpoint, function(self)
		if not self:IsFocus() then
			return
		end
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if needpoint + nowpoint ~= itemprice then
			parent.itemprice:SetText(needpoint + nowpoint)
		end
		parent:Update(needpoint)
	end)
	editbox:SetPoint("TOP", 30, -45);
	frame.needpoint = editbox
	
	local text
	for i = 0, 12 do
		for k, j in ipairs({0, 2, 3, 5}) do
			if i == 0 and j == 0 then
				text = week0
			elseif i == 0 then
				text = format("|cffffff00%dv%d|r", j, j)
			elseif j == 0 then
				text = format(L.week, i)
			else
				text = ""
			end
			frame["r"..i..j] = CreateLabel(frame, text, 16, "TOPRIGHT", "TOPRIGHT", (k-4)*80-60, -80-23*i)
		end
	end
	
	local frame = CreatePanel(cales[3])
	function frame:GetValues()
		return self.itemprice:GetNumber(), self.nowpoint:GetNumber(), self.needpoint:GetNumber(), self.rating:GetNumber()
	end
	function frame:Update(needpoint)
		local need, rating = select(3, self:GetValues())
		needpoint = needpoint or need
		local point 
		for i, v in ipairs({2, 3, 5}) do
			frame["p"..v]:SetFormattedText(L.week2, ceil(needpoint/tAP:RatingToPoint(rating, v)))
		end
	end
	
	editbox = CreateEditBox(frame, L.itemprice, function(self)
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if itemprice - nowpoint ~= needpoint then
			parent.needpoint:SetText(itemprice - nowpoint);
			parent:Update(itemprice - nowpoint)
		end
	end);
	editbox:SetPoint("TOP", 30, -5);
	frame.itemprice = editbox
	
	editbox = CreateEditBox(frame, L.nowpoint, function(self)
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if itemprice - nowpoint ~= needpoint then
			parent.needpoint:SetText(itemprice - nowpoint);
			parent:Update(itemprice - nowpoint)
		end
	end, function(self)
		self:SetText(tonumber(GetArenaCurrency()) or 0);
	end)
	editbox:SetPoint("TOP", 30, -25);
	frame.nowpoint = editbox
	
	editbox = CreateEditBox(frame, L.needpoint, function(self)
		if not self:IsFocus() then
			return
		end
		local parent = self:GetParent()
		local itemprice, nowpoint, needpoint = parent:GetValues();
		if needpoint + nowpoint ~= itemprice then
			parent.itemprice:SetText(needpoint + nowpoint)
		end
		parent:Update(needpoint)
	end)
	editbox:SetPoint("TOP", 30, -45);
	frame.needpoint = editbox
	
	editbox = CreateEditBox(frame, L.vlevel, function(self)
		self:GetParent():Update()
	end, function(self)
		self:SetText(maxRating)
	end)
	editbox:SetPoint("TOP", 30, -65);
	frame.rating = editbox
	
	CreateLabel(frame, L.size, 18, "TOPLEFT", "TOPLEFT", 30,-90)
	CreateLabel(frame, "2v2", 36, "TOPLEFT", "TOPLEFT", 30,-130)
	CreateLabel(frame, "3v3", 36, "TOPLEFT", "TOPLEFT", 30,-230)
	CreateLabel(frame, "5v5", 36, "TOPLEFT", "TOPLEFT", 30,-330)
	
	CreateLabel(frame, L.time, 18, "TOPRIGHT", "TOPRIGHT", -30,-90)
	frame.p2 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-130)
	frame.p3 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-230)
	frame.p5 = CreateLabel(frame, "", 36, "TOPRIGHT", "TOPRIGHT", -30,-330)
	
	PVPFrameArena:ClearAllPoints();
	PVPFrameArena:SetPoint("TOPLEFT", PVPFrameBackground, "TOPLEFT", 0,-95);
	PVPFrameArena:SetWidth(338);
	PVPFrameArena:SetScript("OnMouseUp", function() InterfaceOptionsFrame_OpenToCategory(tAP) end)
	PVPFrameArena:HookScript("OnEnter", function()
		GameTooltip:AddLine(" ")
		GameTooltip:AddLine(L.tooltip)
		GameTooltip:Show()
	end)

	PVPFrameArenaLabel:Hide();
	PVPFrameArenaIcon:Hide();

	PVPFrameArenaPoints:ClearAllPoints();
	PVPFrameArenaPoints:SetPoint("LEFT", 10, 0);

	PVPFrameHonor:SetWidth(220);
	
	PVPFrameArenaRating = PVPFrameArena:CreateFontString(nil, "BACKGROUND");
	PVPFrameArenaRating:SetFontObject("GameFontNormal");
	PVPFrameArenaRating:SetPoint("RIGHT", -10, 0);
end

hooksecurefunc("PVPTeam_Update", function ()
	maxPoint, maxRating = 0, 0
	local button, id, teamSize, teamRating, teamPlayed, playerPlayed, color, playerRating, _, point
	for i = 1, 3 do
		button = _G["PVPTeam"..i];
		id = button:GetID()
		if id and id > 0 then
			teamSize, teamRating, teamPlayed,_,_,_, playerPlayed,_,_, playerRating = select(2, GetArenaTeam(id))
			maxRating = max(maxRating, tonumber(playerRating))
			if teamRating - playerRating > 150 then
				point = tAP:RatingToPoint(playerRating, teamSize);
				color = "*";
			else
				point = tAP:RatingToPoint(teamRating, teamSize);
				color = "";
			end
			if not button.points then
				button.points = button:CreateFontString(nil, "ARTWORK", "GameFontNormal");
				button.points:SetFont(STANDARD_TEXT_FONT, 15, "OUTLINE");	
				button.points:SetPoint("BOTTOMLEFT", "PVPTeam"..i.."DataName", "BOTTOMLEFT", 0, -22);
			end
			if teamPlayed >= 10 and playerPlayed / teamPlayed >= 0.3 then
				color = "|cffa0ffa0%d|r"..color
				maxPoint = max(maxPoint, point)
			else
				color = "|cffff0000%d|r"..color
			end
			button.points:SetFormattedText(color, point)
		elseif button.points then
			button.points:SetText("");
		end		
	end
end)

hooksecurefunc("PVPHonor_Update", function()
	local text = GetArenaCurrency();
	if maxPoint > 0 then
		text = text.." |cffa0ffa0("..(maxPoint + text)..")|r";
	end
	PVPFrameArenaPoints:SetText("|cffffffff"..L.point..": |r" .. text);
	PVPFrameArenaRating:SetText("|cffffffff"..L.prating..": |r" .. (maxRating or 1500))
end)

hooksecurefunc("PVPTeamDetails_Update", function(id)
	local rank, button
	for i = 1, 10 do
		if i <= GetNumArenaTeamMembers(id, 1) then
			button = _G["PVPTeamDetailsButton"..i];
			rank = select(2, GetArenaTeamRosterInfo(id, i));
			
			if rank > 0 then
				if button.leaderIcon then
					button.leaderIcon:Hide();
				end
			else
				if not button.leaderIcon then
					local icon = button:CreateTexture(nil, "OVERLAY");
					icon:SetWidth(16); icon:SetHeight(16);
					icon:SetPoint("RIGHT", button, "LEFT", 13, 0)
					icon:SetTexture("Interface\\GroupFrame\\UI-Group-LeaderIcon")
					button.leaderIcon = icon
				end
				button.leaderIcon:Show();
			end
		end
	end
end)
